// src/composables/useProDrawer.ts
import { ref, h, defineComponent, render, nextTick } from "vue";
import { ElDrawer, ElButton } from "element-plus";
import {
  PlusForm,
  type PlusColumn,
  type FieldValues
} from "plus-pro-components";

interface DrawerOptions {
  title?: string;
  formModel?: FieldValues;
  formSchema?: PlusColumn[];
  formRules?: Record<string, any>;
  customContent?: () => ReturnType<typeof h>;
  onSubmit?: (formModel: FieldValues) => void;
  beforeSubmit?: (formModel: FieldValues) => boolean | Promise<boolean>;
  onSubmitError?: (errors: any) => void;
  drawerProps?: Record<string, any>;
}

const useProDrawer = () => {
  const visible = ref(false);
  const formModel = ref<FieldValues>({});
  const formRef = ref<InstanceType<typeof PlusForm> | null>(null);
  let onSubmit: DrawerOptions["onSubmit"];
  let onSubmitError: DrawerOptions["onSubmitError"];
  let beforeSubmit: DrawerOptions["beforeSubmit"];
  let options: DrawerOptions | null = null;

  const ProDrawerComponent = defineComponent({
    setup() {
      const handleConfirm = async () => {
        if (beforeSubmit) {
          const proceed = await beforeSubmit(formModel.value);
          if (!proceed) return;
        }

        if (formRef.value) {
          try {
            const isValid = await new Promise<boolean>(resolve => {
              formRef.value?.handleSubmit(valid => resolve(valid));
            });

            if (isValid) {
              if (onSubmit) {
                onSubmit(formModel.value);
              }
              formRef.value.handleReset();
              visible.value = false;
            } else {
              console.error("表单验证失败");
            }
          } catch (error) {
            console.error("表单提交过程中发生错误", error);
          }
        }
      };

      const handleCancel = () => {
        visible.value = false;
      };

      const handleSubmitError = (errors: any) => {
        if (onSubmitError) {
          onSubmitError(errors);
        }
        console.error("表单提交错误", errors);
      };

      return () =>
        h(
          ElDrawer,
          {
            modelValue: visible.value,
            title: options?.title || "Pro Drawer",
            width: "50%",
            onClose: handleCancel,
            ...(options?.drawerProps || {})
          },
          {
            default: () => [
              options?.formSchema?.length
                ? h(PlusForm, {
                    ref: formRef,
                    model: formModel.value,
                    columns: options.formSchema,
                    rules: options.formRules,
                    hasFooter: false,
                    onSubmit: formModel => {
                      if (onSubmit) {
                        onSubmit(formModel);
                      }
                      formRef.value?.handleReset();
                      visible.value = false;
                    },
                    onSubmitError: handleSubmitError
                  })
                : null,
              options?.customContent ? options.customContent() : null,
              h("div", { style: "text-align: right; margin-top: 20px;" }, [
                h(
                  ElButton,
                  { onClick: handleCancel },
                  { default: () => "取消" }
                ), // Using function slot for better performance
                h(
                  ElButton,
                  {
                    type: "primary",
                    onClick: handleConfirm,
                    style: "margin-left: 8px;"
                  },
                  { default: () => "确认" } // Using function slot for better performance
                )
              ])
            ]
          }
        );
    }
  });

  let container: HTMLElement | null = null;

  const openDrawer = (opts: DrawerOptions) => {
    options = opts;
    formModel.value = opts.formModel || {};
    onSubmit = opts.onSubmit;
    beforeSubmit = opts.beforeSubmit;
    onSubmitError = opts.onSubmitError;
    visible.value = true;

    if (!container) {
      container = document.createElement("div");
      document.body.appendChild(container);
      render(h(ProDrawerComponent), container);
    } else {
      nextTick(() => {
        render(h(ProDrawerComponent), container);
      });
    }
  };

  return { openDrawer };
};

export default useProDrawer;
